package com.xgl.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

/**
 * @包名 com.xgl.pojo
 * @创建人 熊国林
 * @创建时间 2021/5/20
 * @描述 区块链
 */
@Data
@AllArgsConstructor
public class Chain {
    ArrayList<Block> chain = new ArrayList<>();
    int difficulty;//设置区块添加到区块链的难度

    /**
     * Chain构造函数，执行添加祖先区块
     */
    public Chain() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        chain.add(bigBang());
        difficulty = 5;//设置这条区块链挖矿的难度为5
    }

    /*
     * 生成祖先区块
     */
    public Block bigBang() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        Block genesisBlock = new Block("我是祖先区块", "");
        genesisBlock.Hash = genesisBlock.computeHash();
        return genesisBlock;
    }

    /**
     * 增加新区块到区块链中
     * 找到最近一个block的hash，即为最新区块的previousHash
     */
    public void addBlockToChain(Block newBlock){
        newBlock.previousHash = getLatesBlock().Hash;
//		newBlock.Hash = newBlock.computeHash();
        /**
         * 这里的hash值需要满足一个区块链的条件，即难度（difficult）
         */
        //newBlock.mine(difficulty);
        chain.add(newBlock);

    }

    /**
     * 找到最后的一个区块
     */
    public Block getLatesBlock(){
        return chain.get(chain.size() - 1);
    }

    /**
     * 验证当前区块链是否被修改
     * 判断条件：当前区块的previousHash是否等于上一个区块的hash
     */

    public boolean validateChain() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if(chain.size() == 1){
            if(chain.get(0).Hash.equals(chain.get(0).computeHash())){
                return true;
            }
            return false;
        }

        /**
         * chain[1]是第二个区块
         * 从第二个区块开始验证，直到最后一个区块->chain.size-1（类似于数组）
         */
        for(int i = 1; i <= chain.size()-1; i++){

            //先验证当前区块数据是否被修改
            Block blockToValidate = chain.get(i);
            if(!blockToValidate.Hash.equals(blockToValidate.computeHash())){
                System.out.print("当前区块链已经被修改！");
                return false;
            }

            //验证当前区块的previousHash是否等于previous区块的hash
            Block previousBlock = chain.get(i - 1);
            if(blockToValidate.previousHash != previousBlock.Hash){
                System.out.print("前后区块链发生断裂");
                return false;
            }
        }
        return true;
    }

    @Override
    public String toString() {
        return "Chain = "+ chain + "\n";
    }
}
